Série Temporal do Clima na região de Petrolina-PE¶

Uma série temporal é definida como um conjunto de observações registradas ao longo do tempo, organizadas de forma cronológica. Esse tipo de análise permite identificar padrões, tendências e ciclos que podem surgir em diversos contextos, como economia, saúde, e, especialmente, no campo da meteorologia.

O estudo de variáveis meteorológicas, como a precipitação, tem ganhado cada vez mais destaque devido à crescente importância de compreender os impactos das mudanças climáticas. Com o aumento da frequência e intensidade dos eventos climáticos extremos, como secas, inundações e tempestades severas, o monitoramento e a análise detalhada dessas séries temporais tornam-se ferramentas essenciais para prever e mitigar possíveis desastres naturais. Além disso, esses estudos permitem uma melhor compreensão das dinâmicas climáticas em longo prazo, auxiliando na formulação de políticas públicas voltadas para a adaptação e mitigação das consequências dessas alterações no clima global.

In [667]:
using CSV, DataFrames, StatsPlots, Dates, Plots, StatsBase, GLM
theme(:wong)
In [668]:
readdir()
34-element Vector{String}:
 "INMET.ipynb"
 "INMET_NE_PE_A307_PETROLINA_01-01-2004_A_31-12-2004.CSV"
 "INMET_NE_PE_A307_PETROLINA_01-01-2005_A_31-12-2005.CSV"
 "INMET_NE_PE_A307_PETROLINA_01-01-2006_A_31-12-2006.CSV"
 "INMET_NE_PE_A307_PETROLINA_01-01-2007_A_31-12-2007.CSV"
 "INMET_NE_PE_A307_PETROLINA_01-01-2008_A_31-12-2008.CSV"
 "INMET_NE_PE_A307_PETROLINA_01-01-2009_A_31-12-2009.CSV"
 "INMET_NE_PE_A307_PETROLINA_01-01-2010_A_31-12-2010.CSV"
 "INMET_NE_PE_A307_PETROLINA_01-01-2011_A_31-12-2011.CSV"
 "INMET_NE_PE_A307_PETROLINA_01-01-2012_A_31-12-2012.CSV"
 ⋮
 "kmeans.ipynb"
 "questões_de_concursos.ipynb"
 "regressao_linear.ipynb"
 "shapley_value.ipynb"
 "src copy.html"
 "src copy.ipynb"
 "src_plotlyjs.ipynb"
 "subplots_temperatura_mensal.png"
 "subplots_temperatura_mensal_sem_xlabel.png"
In [669]:
# Lista de arquivos CSV
arquivos_csv = [
    "INMET_NE_PE_A307_PETROLINA_21-02-2003_A_31-12-2003.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2004_A_31-12-2004.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2005_A_31-12-2005.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2006_A_31-12-2006.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2007_A_31-12-2007.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2008_A_31-12-2008.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2009_A_31-12-2009.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2010_A_31-12-2010.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2011_A_31-12-2011.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2012_A_31-12-2012.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2013_A_31-12-2013.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2014_A_31-12-2014.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2015_A_31-12-2015.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2016_A_31-12-2016.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2017_A_31-12-2017.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2018_A_31-12-2018.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2019_A_31-12-2019.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2020_A_31-12-2020.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2021_A_31-12-2021.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2022_A_31-12-2022.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2023_A_31-12-2023.CSV",
    "INMET_NE_PE_A307_PETROLINA_01-01-2024_A_31-12-2024.CSV",
]

# Função para renomear as colunas pela sua sequência numérica
function renomear_colunas(df::DataFrame)
    nomes_novos = ["col_$i" for i in 1:ncol(df)]  # Gerar nomes 'col_1', 'col_2', etc.
    rename!(df, nomes_novos)
end
renomear_colunas (generic function with 1 method)
In [670]:
# Dicionário de renomeação das colunas
dicionario_renomeacao = Dict(
    "col_1" => :DATA,
    "col_2" => :HORA,
    "col_3" => :PRECIP_mm,
    "col_4" => :PRESSAO_ATMOSFERICA_NIVEL_ESTACAO_mb,
    "col_5" => :PRESSAO_ATMOSFERICA_MAX_mb,
    "col_6" => :PRESSAO_ATMOSFERICA_MIN_mb,
    "col_7" => :RADIACAO_GLOBAL_kjm2,
    "col_8" => :TEMPERATURA_AR_BULBO_SECO,
    "col_9" => :TEMPERATURA_PONTO_DE_ORVALHO,
    "col_10" => :TEMPERATURA_MAXIMA,
    "col_11" => :TEMPERATURA_MINIMA,
    "col_12" => :TEMPERATURA_ORVALHO_MAX,
    "col_13" => :TEMPERATURA_ORVALHO_MIN,
    "col_14" => :UMIDADE_RELATIVA_MAXIMA_percent,
    "col_15" => :UMIDADE_RELATIVA_MINIMA_percent,
    "col_16" => :UMIDADE_RELATIVA_AR_percent,
    "col_17" => :VENTO_DIRECAO,
    "col_18" => :VENTO_RAJADA_MAXIMA_ms,
    "col_19" => :VENTO_VELOCIDADE_ms
)
Dict{String, Symbol} with 19 entries:
  "col_12" => :TEMPERATURA_ORVALHO_MAX
  "col_13" => :TEMPERATURA_ORVALHO_MIN
  "col_7"  => :RADIACAO_GLOBAL_kjm2
  "col_15" => :UMIDADE_RELATIVA_MINIMA_percent
  "col_1"  => :DATA
  "col_10" => :TEMPERATURA_MAXIMA
  "col_6"  => :PRESSAO_ATMOSFERICA_MIN_mb
  "col_8"  => :TEMPERATURA_AR_BULBO_SECO
  "col_14" => :UMIDADE_RELATIVA_MAXIMA_percent
  "col_19" => :VENTO_VELOCIDADE_ms
  "col_3"  => :PRECIP_mm
  "col_18" => :VENTO_RAJADA_MAXIMA_ms
  "col_4"  => :PRESSAO_ATMOSFERICA_NIVEL_ESTACAO_mb
  "col_11" => :TEMPERATURA_MINIMA
  "col_9"  => :TEMPERATURA_PONTO_DE_ORVALHO
  "col_16" => :UMIDADE_RELATIVA_AR_percent
  "col_17" => :VENTO_DIRECAO
  "col_2"  => :HORA
  "col_5"  => :PRESSAO_ATMOSFERICA_MAX_mb
In [671]:
# Função para renomear as colunas de acordo com o dicionário
function renomear_colunas_dicionario(df::DataFrame, dicionario::Dict)
    rename!(df, dicionario)
end
renomear_colunas_dicionario (generic function with 1 method)
In [672]:
# Carregar todos os CSVs, renomear as colunas sequenciais e aplicar o dicionário de renomeação
df = vcat([renomear_colunas_dicionario(renomear_colunas(CSV.read(arquivo, DataFrame; delim=';')), dicionario_renomeacao) for arquivo in arquivos_csv]...)
191640×19 DataFrame
191615 rows omitted
RowDATAHORAPRECIP_mmPRESSAO_ATMOSFERICA_NIVEL_ESTACAO_mbPRESSAO_ATMOSFERICA_MAX_mbPRESSAO_ATMOSFERICA_MIN_mbRADIACAO_GLOBAL_kjm2TEMPERATURA_AR_BULBO_SECOTEMPERATURA_PONTO_DE_ORVALHOTEMPERATURA_MAXIMATEMPERATURA_MINIMATEMPERATURA_ORVALHO_MAXTEMPERATURA_ORVALHO_MINUMIDADE_RELATIVA_MAXIMA_percentUMIDADE_RELATIVA_MINIMA_percentUMIDADE_RELATIVA_AR_percentVENTO_DIRECAOVENTO_RAJADA_MAXIMA_msVENTO_VELOCIDADE_ms
String15AnyString7?String7?String7?String7?AnyString7?String7?String7?String7?String7?String7?Int64?Int64?Int64?Int64?String7?String7?
121/02/200300:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
221/02/200301:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
321/02/200302:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
421/02/200303:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
521/02/200304:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
621/02/200305:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
721/02/200306:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
821/02/200307:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
921/02/200308:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
1021/02/200309:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
1121/02/200310:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
1221/02/200311:00:000971,1-9999-9999-999925,519,6-9999-9999-9999-9999-9999-999970124-99993,5
1321/02/200312:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮
19162931/12/20241200 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
19163031/12/20241300 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
19163131/12/20241400 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
19163231/12/20241500 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
19163331/12/20241600 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
19163431/12/20241700 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
19163531/12/20241800 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
19163631/12/20241900 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
19163731/12/20242000 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
19163831/12/20242100 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
19163931/12/20242200 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
19164031/12/20242300 UTCmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissingmissing
In [673]:
# Converter a coluna DATA para o tipo Date
df.DATA = Date.(df.DATA, "dd/mm/yyyy")
191640-element Vector{Date}:
 2003-02-21
 2003-02-21
 2003-02-21
 2003-02-21
 2003-02-21
 2003-02-21
 2003-02-21
 2003-02-21
 2003-02-21
 2003-02-21
 ⋮
 2024-12-31
 2024-12-31
 2024-12-31
 2024-12-31
 2024-12-31
 2024-12-31
 2024-12-31
 2024-12-31
 2024-12-31
In [674]:
describe(df)
19×7 DataFrame
Rowvariablemeanminmedianmaxnmissingeltype
SymbolUnion…AnyAnyAnyInt64Type
1DATA2003-02-212014-01-262024-12-310Date
2HORA0Any
3PRECIP_mm-99999,811768Union{Missing, String7}
4PRESSAO_ATMOSFERICA_NIVEL_ESTACAO_mb-9999980,711695Union{Missing, String7}
5PRESSAO_ATMOSFERICA_MAX_mb-9999980,811696Union{Missing, String7}
6PRESSAO_ATMOSFERICA_MIN_mb-9999980,511696Union{Missing, String7}
7RADIACAO_GLOBAL_kjm235916Any
8TEMPERATURA_AR_BULBO_SECO-999940,911695Union{Missing, String7}
9TEMPERATURA_PONTO_DE_ORVALHO-99999,911699Union{Missing, String7}
10TEMPERATURA_MAXIMA-999943,311696Union{Missing, String7}
11TEMPERATURA_MINIMA-999938,411696Union{Missing, String7}
12TEMPERATURA_ORVALHO_MAX-99999,911700Union{Missing, String7}
13TEMPERATURA_ORVALHO_MIN-99999,911700Union{Missing, String7}
14UMIDADE_RELATIVA_MAXIMA_percent-397.023-999956.09811700Union{Missing, Int64}
15UMIDADE_RELATIVA_MINIMA_percent-401.456-999950.09811700Union{Missing, Int64}
16UMIDADE_RELATIVA_AR_percent-393.804-999953.09811699Union{Missing, Int64}
17VENTO_DIRECAO-325.604-9999126.036011696Union{Missing, Int64}
18VENTO_RAJADA_MAXIMA_ms-99999,911697Union{Missing, String7}
19VENTO_VELOCIDADE_ms-99999,811696Union{Missing, String7}
In [675]:
# Converter os valores ausentes em uma matriz booleana
missing_values = Matrix{Bool}(ismissing.(df))

# Criar o mapa de calor
p = heatmap(missing_values, 
            xlabel="Columns", ylabel="Rows", 
            title="Missing Values Heatmap", 
            colorbar=false,  # Remover a legenda (barra de cores)
            color=cgrad([:grey10, :white]),  # Escala de cores em preto e branco
            xticks=(1:size(missing_values, 2), names(df)),  # Adicionar os nomes das colunas no xtick
            rotation=90,  # Rotacionar os rótulos das colunas
            formatter=:plain,
            size=(1000, 800))  # Aumentar a resolução do gráfico

# Adicionar linhas verticais entre as colunas
for x in 1.5:1:(size(missing_values, 2) - 0.5)
    vline!([x], linecolor=:white, linewidth=1, label="")
end

display(p)
In [676]:
# Remover as linhas que contém valores Missing
df = dropmissing(df)
155724×19 DataFrame
155699 rows omitted
RowDATAHORAPRECIP_mmPRESSAO_ATMOSFERICA_NIVEL_ESTACAO_mbPRESSAO_ATMOSFERICA_MAX_mbPRESSAO_ATMOSFERICA_MIN_mbRADIACAO_GLOBAL_kjm2TEMPERATURA_AR_BULBO_SECOTEMPERATURA_PONTO_DE_ORVALHOTEMPERATURA_MAXIMATEMPERATURA_MINIMATEMPERATURA_ORVALHO_MAXTEMPERATURA_ORVALHO_MINUMIDADE_RELATIVA_MAXIMA_percentUMIDADE_RELATIVA_MINIMA_percentUMIDADE_RELATIVA_AR_percentVENTO_DIRECAOVENTO_RAJADA_MAXIMA_msVENTO_VELOCIDADE_ms
DateAnyString7String7String7String7AnyString7String7String7String7String7String7Int64Int64Int64Int64String7String7
12003-02-2100:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
22003-02-2101:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
32003-02-2102:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
42003-02-2103:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
52003-02-2104:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
62003-02-2105:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
72003-02-2106:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
82003-02-2107:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
92003-02-2108:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
102003-02-2109:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
112003-02-2110:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
122003-02-2111:00:000971,1-9999-9999-999925,519,6-9999-9999-9999-9999-9999-999970124-99993,5
132003-02-2112:00:00-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999-9999
⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮⋮
1557132022-08-101100 UTC0976,5976,5975,676,42016,220,119,816,2167978791146,33,3
1557142022-08-101200 UTC0977977976,5251,820,715,8212016,415,77973731376,53,4
1557152022-08-101300 UTC0977,2977,3977461,521,615,821,620,716,115,77470701176,83,8
1557162022-08-101400 UTC0976,3977,2976,32013,724,914,72521,616,214,27053531377,44,4
1557172022-08-101500 UTC0975,3976,3975,32347,926,31526,824,315,714,25449501347,54
1557182022-08-101600 UTC0974,1975,3974,12493,327,114,128,425,815,213,95043451247,32,9
1557192022-08-101700 UTC0972,6974,2972,62375,429,113,129,926,9151346373710862,5
1557202022-08-101800 UTC0971,6972,6971,62077,530,412,430,928,913,711,83832331645,11,5
1557212022-08-101900 UTC0971,3971,6971,31610,730,610,33129,712,69,23326281497,10,6
1557222022-08-102000 UTC0970,9971,3970,91013,430,87,331,530,510,77,3292323883,91,7
1557232022-08-102100 UTC0970,8970,9970,8368,129,89,730,929,89,97,32923291493,40,6
1557242022-08-102200 UTC0970,9970,9970,83,226,39,729,826,19,89,33628351682,20
Explicação das Correções:¶
  1. Conversão para String:
  • Usamos string(valor) para garantir que todos os valores sejam convertidos para strings antes de aplicar replace.

  • Isso resolve o problema com tipos como String7.

  1. Substituição e Conversão:
  • Aplicamos replace(string(valor), "," => ".") para substituir vírgulas por pontos.

  • Usamos parse(Float64, ...) para converter os valores resultantes para Float64.

  1. Verificação de Tipo:
  • A função substituir_virgulas_por_pontos verifica se o valor é do tipo String ou String7 antes de aplicar a substituição.

  • Valores que não são strings (como números inteiros) são mantidos inalterados.

In [677]:
# Função para substituir vírgulas por pontos em valores que são strings
function substituir_virgulas_por_pontos(valor)
    # Converte o valor para string, substitui vírgulas por pontos e tenta converter para Float64
    if valor isa Union{String, String7}
        return parse(Float64, replace(string(valor), "," => "."))
    else
        return valor
    end
end

# Aplicar a função a todas as colunas do DataFrame
for col in names(df)
    df[!, col] = substituir_virgulas_por_pontos.(df[!, col])
end
In [678]:
println("Número de linhas antes da remoção: ", nrow(df))
df = DataFrame(filter(row -> all(x -> !(ismissing(x) || x == -9999), row), eachrow(df)))
println("Número de linhas após a remoção: ", nrow(df))
Número de linhas antes da remoção: 155724
Número de linhas após a remoção: 77811
77811
In [679]:
describe(df)
19×7 DataFrame
Rowvariablemeanminmedianmaxnmissingeltype
SymbolUnion…AnyAnyAnyInt64DataType
1DATA2003-02-212013-12-102022-08-100Date
2HORA0Any
3PRECIP_mm0.04587010.00.047.40Float64
4PRESSAO_ATMOSFERICA_NIVEL_ESTACAO_mb970.901961.7970.9980.70Float64
5PRESSAO_ATMOSFERICA_MAX_mb971.312961.8971.3980.80Float64
6PRESSAO_ATMOSFERICA_MIN_mb970.676961.6970.7980.50Float64
7RADIACAO_GLOBAL_kjm23296.590.01516.650086.00Real
8TEMPERATURA_AR_BULBO_SECO28.565817.428.839.00Float64
9TEMPERATURA_PONTO_DE_ORVALHO15.55081.015.823.60Float64
10TEMPERATURA_MAXIMA29.111317.729.440.70Float64
11TEMPERATURA_MINIMA27.571917.327.638.00Float64
12TEMPERATURA_ORVALHO_MAX16.20031.916.424.90Float64
13TEMPERATURA_ORVALHO_MIN15.12770.615.422.60Float64
14UMIDADE_RELATIVA_MAXIMA_percent51.95071151.0950Int64
15UMIDADE_RELATIVA_MINIMA_percent46.73381045.0950Int64
16UMIDADE_RELATIVA_AR_percent48.241146.0950Int64
17VENTO_DIRECAO122.3991124.03600Int64
18VENTO_RAJADA_MAXIMA_ms7.789120.07.924.20Float64
19VENTO_VELOCIDADE_ms3.677760.03.710.40Float64
In [680]:
# Extrair o ano de cada data
df.ANO = year.(df.DATA)

# Contar a quantidade de valores por ano
contagem_por_ano = combine(groupby(df, :ANO), nrow => :QUANTIDADE)

# Ordenar o DataFrame por ano (opcional, mas útil para visualização)
sort!(contagem_por_ano, :ANO)

# Criar o gráfico de barras
bar(contagem_por_ano.ANO, 
    contagem_por_ano.QUANTIDADE, 
    xlabel="Ano", 
    ylabel="Quantidade de Valores", 
    title="", 
    legend=false, 
    color=:dodgerblue, 
    alpha=0.6,
    lw=0,
    xticks=contagem_por_ano.ANO,  # Garantir que todos os anos apareçam no eixo x
    xrotation=45,  # Rotacionar os rótulos do eixo x para melhor legibilidade
    ylim=(0, maximum(contagem_por_ano.QUANTIDADE) * 1.2))  # Ajustar o limite superior do eixo y

# Adicionar os valores em cima de cada barra com rotação
for (i, quantidade) in enumerate(contagem_por_ano.QUANTIDADE)
    annotate!(contagem_por_ano.ANO[i], quantidade + 0.05 * maximum(contagem_por_ano.QUANTIDADE), 
              text("$quantidade", :center, 8, rotation=45))  # Rotacionar o texto em 45 graus
end

# Exibir o gráfico
plot!()
In [681]:
# Definir os dados para os plots
df_temperatura_minima = df[!, :TEMPERATURA_MINIMA]
df_temperatura_maxima = df[!, :TEMPERATURA_MAXIMA]

# Ajustar o número de bins para os histogramas
p1 = histogram(df_temperatura_minima, bins = 20, alpha=0.6, color = :dodgerblue, lw = 0, title = "Distribuição da Temperatura Mínima", legend=:none)
p2 = histogram(df_temperatura_maxima, bins = 20, alpha=0.6, color = :dodgerblue, lw = 0, title = "Distribuição da Temperatura Máxima", legend=:none)
p3 = boxplot(["TEMPERATURA MÍNIMA", "TEMPERATURA MÁXIMA"], [df_temperatura_minima, df_temperatura_maxima], alpha=0.6, title = "Boxplot das Temperaturas")

# Definir o layout com 3 plots
layout = @layout([a b; c])

# Juntar os gráficos e adicionar o título principal
plot(p1, p2, p3, layout = layout, size = (900, 500), title = "", titlefontsize = 10, formatter = :plain, widen=true)
In [682]:
# Criar o gráfico
plot(df.DATA, df.TEMPERATURA_AR_BULBO_SECO,
     title = "Temperatura ao Longo do Tempo",
     xlabel = "Data",
     ylabel = "Temperatura (°C)",
     legend = false,
     lw = 2,
     size = (800, 400))    # Ajustar o tamanho (largura, altura))  # lw define a espessura da linha
In [683]:
# Média
media = mean(df.TEMPERATURA_AR_BULBO_SECO)
# Mediana
mediana = median(df.TEMPERATURA_AR_BULBO_SECO)
# Moda (usando a função mode de StatsBase)
moda = mode(df.TEMPERATURA_AR_BULBO_SECO)
# Variância
variancia = var(df.TEMPERATURA_AR_BULBO_SECO)
# Desvio padrão
desvio_padrao = std(df.TEMPERATURA_AR_BULBO_SECO)
# Coeficiente de variação
coef_variacao = (desvio_padrao / media) * 100
# Amplitude (diferença entre o maior e o menor valor)
amplitude = maximum(df.TEMPERATURA_AR_BULBO_SECO) - minimum(df.TEMPERATURA_AR_BULBO_SECO)
# Quartis
q1 = quantile(df.TEMPERATURA_AR_BULBO_SECO, 0.25)  # Primeiro quartil (Q1)
q3 = quantile(df.TEMPERATURA_AR_BULBO_SECO, 0.75)  # Terceiro quartil (Q3)
# Intervalo interquartil (IQR)
iqr = q3 - q1

println("Média: $media")
println("Mediana: $mediana")
println("Moda: $moda")
println("Variância: $variancia")
println("Desvio padrão: $desvio_padrao")
println("Coeficiente de variação: $coef_variacao%")
println("Amplitude: $amplitude")
println("Primeiro Quartil (Q1): $q1")
println("Terceiro Quartil (Q3): $q3")
println("Intervalo Interquartil (IQR): $iqr")
Média: 28.565810746552543
Mediana: 28.8
Moda: 29.3
Variância: 15.233916158964835
Desvio padrão: 3.9030649698621254
Coeficiente de variação: 13.663413947854309%
Amplitude: 21.6
Primeiro Quartil (Q1): 25.5
Terceiro Quartil (Q3): 31.7
Intervalo Interquartil (IQR): 6.199999999999999
In [684]:
# Criando o histograma com a sobreposição da densidade
histogram(df.TEMPERATURA_AR_BULBO_SECO,
          bins=30,                # Número de bins
          normalize=true,         # Normaliza o histograma para densidade
          color=:dodgerblue,         # Cor das barras do histograma
          edgecolor=:black,       # Cor das bordas das barras
          xlabel="Temperatura (°C)",
          ylabel="Densidade",
          title="Histograma com Sobreposição de Distribuição para Temperatura (°C)",
          titlefontsize=10,       # Diminuindo o tamanho da fonte do título
          alpha=0.6,              # Transparência do histograma
          lw=0,
          legend=false)           # Sem legenda para o histograma

# Sobrepondo a densidade (curva de distribuição)
density!(df.TEMPERATURA_AR_BULBO_SECO,
         color=:blue,          # Cor da linha de densidade
         lw=2,            # Espessura da linha de densidade
         alpha=0.6)              # Transparência da curva de densidade
In [685]:
boxplot(df.TEMPERATURA_AR_BULBO_SECO,
        xlabel="", ylabel="Temperatura [C°]", title="Boxplot da Temperatura do ar bulbo seco",
        legend=false,  # Remover a legenda, já que só temos uma série de dados
        color=:lightpink,  # Cor das caixas
        boxwidth=0.3,  # Ajuste da largura das caixas
        whiskercolor=:black,  # Cor das linhas dos bigodes
        fliercolor=:red,  # Cor dos outliers
        fliermarker=:circle,  # Estilo dos marcadores dos outliers
        mediancolor=:black,  # Cor da linha da mediana
        medianwidth=3,  # Espessura da linha da mediana
        grid=true,  # Adicionar grid
        titlefontsize=14,  # Tamanho da fonte do título
        labelfontsize=12,  # Tamanho da fonte dos rótulos
        tickfontsize=10)  # Tamanho da fonte dos ticks
In [686]:
# Formatando as datas para extrair o mês e ano
df.MonthYear = Dates.format.(df.DATA, "yyyymm")

# Calculando a média de temperatura por mês
monthly_avg_temp = combine(groupby(df, :MonthYear), :TEMPERATURA_AR_BULBO_SECO => mean => :AvgTemperature)

# Convertendo MonthYear de volta para Date para plotagem adequada
monthly_avg_temp.MonthYear = Date.(monthly_avg_temp.MonthYear, "yyyymm")

# Criando o gráfico de linha com as médias mensais de temperatura
plot(
    monthly_avg_temp.MonthYear, monthly_avg_temp.AvgTemperature,
    xlabel = "Date", ylabel = "Average Temperature (°C)",
    title = "Average Monthly Temperature", 
    label = "Average Temp [°C]", legend = :none,
    lw = 2, markershape = :circle, markercolor = :steelblue,
    xrotation = 0,  # Rotacionando os rótulos do eixo X
    size = (1200, 200)  # Esticando o gráfico para os lados (largura maior)
)
In [687]:
# Formatando as datas para formato "jan 2013"
formatted_dates = [Dates.format(d, "u yyyy") for d in df.DATA];
# Extraindo as datas únicas de cada mês (por exemplo, pegando o primeiro dia de cada mês)
unique_months = unique(Dates.yearmonth.(df.DATA));
# Filtrando as datas para mostrar apenas uma por mês
tick_positions = [findfirst(x -> Dates.yearmonth(x) == month, df.DATA) for month in unique_months];
In [688]:
# Filtrando os dados para incluir apenas o ano de 2013
df_2021 = filter(row -> year(row.DATA) == 2021, df)

# Formatando as datas para o formato "jan 2013"
formatted_dates = [Dates.format(d, "u yyyy") for d in df_2021.DATA]

# Extraindo as datas únicas de cada mês para 2013 (por exemplo, pegando o primeiro dia de cada mês)
unique_months = unique(Dates.yearmonth.(df_2021.DATA))

# Filtrando as datas para mostrar apenas uma por mês
tick_positions = [findfirst(x -> Dates.yearmonth(x) == month, df_2021.DATA) for month in unique_months]

# Criando o gráfico com a escala de temperatura em Celsius
scatter(
    df_2021.DATA, df_2021.TEMPERATURA_AR_BULBO_SECO,
    label = "Temperatura [°C]",
    color = :lightblue, alpha = 0.6, xlabel = "", ylabel = "Temperatura [°C]", 
    legend = :topright,  # Adicionando a legenda
    legendfontsize = 8,  # Diminuindo o tamanho da fonte da legenda
    ylims = (0, 50),
    linewidth = 1.5,
    yticks = 0:10:50,  # Definindo ticks de 10 em 10 no eixo Y
    tickfontsize = 8,  # Diminuindo o tamanho da fonte dos ticks
    guidefontsize = 8,  # Diminuindo o tamanho das fontes dos rótulos
    xticks = (df_2021.DATA[tick_positions], formatted_dates[tick_positions]),  # Ajustando os rótulos e suas posições
    xrotation = 20  # Rotacionando os rótulos do eixo X em 45 graus
)
In [689]:
# Criando o gráfico com a escala de temperatura em Celsius
scatter(
    df_2021.DATA, df_2021.TEMPERATURA_AR_BULBO_SECO,
    label = "Temperatura [°C]",
    color=:coolwarm,
    zcolor=df_2021[!, :TEMPERATURA_AR_BULBO_SECO] ./ maximum(df_2021[!, :TEMPERATURA_AR_BULBO_SECO]),
    alpha = 0.6,
    xlabel = "",
    ylabel = "Temperatura [°C]", 
    legend = :topright,  # Adicionando a legenda
    legendfontsize = 8,  # Diminuindo o tamanho da fonte da legenda
    ylims = (0, 50),
    linewidth = 1.5,
    yticks = 0:10:50,  # Definindo ticks de 10 em 10 no eixo Y
    tickfontsize = 8,  # Diminuindo o tamanho da fonte dos ticks
    guidefontsize = 8,  # Diminuindo o tamanho das fontes dos rótulos
    xticks = (df_2021.DATA[tick_positions], formatted_dates[tick_positions]),  # Ajustando os rótulos e suas posições
    xrotation = 20  # Rotacionando os rótulos do eixo X em 45 graus
)
In [690]:
# Filtrando os dados para o mês de junho de 2013
junho_2021 = df_2021[month.(df_2021.DATA) .== 6, :]

# Criando o gráfico com a escala de temperatura em Celsius
p = scatter(
    df_2021.DATA, df_2021.TEMPERATURA_AR_BULBO_SECO,
    label = "2013",
    color = :lightblue, alpha = 0.6, xlabel = "", ylabel = "Temperatura [°C]", 
    legend = :topright,
    legendfontsize = 8,  # Diminuindo o tamanho da fonte da legenda
    ylims = (0, 50),
    linewidth = 1.5,
    yticks = 0:10:50,  # Definindo ticks de 10 em 10 no eixo Y
    tickfontsize = 8,  # Diminuindo o tamanho da fonte dos ticks
    guidefontsize = 8,   # Diminuindo o tamanho das fontes dos rótulos
    xticks = (df_2021.DATA[tick_positions], formatted_dates[tick_positions]),  # Ajustando os rótulos e suas posições
    xrotation = 20  # Rotacionando os rótulos do eixo X em 20 graus
)

# Adicionando os pontos de junho de 2013 em vermelho
scatter!(
    junho_2021.DATA, junho_2021.TEMPERATURA_AR_BULBO_SECO, 
    color = :red, label = "Junho 2013", markersize = 3
)

# Exibir o gráfico
display(p)
In [691]:
# Filtrando os dados para o mês de junho de 2013 com temperaturas maiores que 30°C
junho_maior_30_data = df_2021[(month.(df_2021.DATA) .== 6) .& (df_2021.TEMPERATURA_AR_BULBO_SECO .> 30), :]

# Criando o gráfico com a escala de temperatura em Celsius
p = scatter(
    df_2021.DATA, df_2021.TEMPERATURA_AR_BULBO_SECO,
    label = "2013",
    color = :lightblue, alpha = 0.6, xlabel = "", ylabel = "Temperatura [°C]", 
    legend = :topright,
    legendfontsize = 8,  # Diminuindo o tamanho da fonte da legenda
    ylims = (0, 50),
    linewidth = 1.5,
    yticks = 0:10:50,  # Definindo ticks de 10 em 10 no eixo Y
    tickfontsize = 8,  # Diminuindo o tamanho da fonte dos ticks
    guidefontsize = 8,   # Diminuindo o tamanho das fontes dos rótulos
    xticks = (df_2021.DATA[tick_positions], formatted_dates[tick_positions]),  # Ajustando os rótulos e suas posições
    xrotation = 20  # Rotacionando os rótulos do eixo X em 20 graus
)

# Adicionando os pontos de junho de 2013 com temperatura > 30°C em vermelho
scatter!(
    junho_maior_30_data.DATA, junho_maior_30_data.TEMPERATURA_AR_BULBO_SECO, 
    color = :red, label = "Junho > 30°C", markersize = 3
)

# Exibir o gráfico
display(p)
In [692]:
# Criando o gráfico de dispersão para as duas variáveis de temperatura
scatter(
    df_2021.DATA, df.TEMPERATURA_MINIMA,
    label = "Temperatura Mínima [°C]",
    color = :lightblue, alpha = 0.5, xlabel = "Data", ylabel = "Temperatura [°C]",
    legend = :topright,
    legendfontsize = 8,  # Diminuindo o tamanho da fonte da legenda
    ylims = (0, 50),
    linewidth = 1.5,
    yticks = 0:10:50,  # Definindo ticks de 10 em 10 no eixo Y
    tickfontsize = 8,  # Diminuindo o tamanho da fonte dos ticks
    guidefontsize = 8,   # Diminuindo o tamanho das fontes dos rótulos
    xticks = (df.DATA[tick_positions], formatted_dates[tick_positions]),  # Ajustando os rótulos e suas posições
    xrotation = 20  # Rotacionando os rótulos do eixo X em 45 graus
)

scatter!(
    df_2021.DATA, df.TEMPERATURA_MAXIMA,
    label = "Temperatura Máxima [°C]",
    color = :red, alpha = 0.1,
    linewidth = 1.5
)
In [693]:
# Supondo que 'df' seja o DataFrame que contém os dados de vários anos
# Primeiramente, vamos adicionar uma coluna com o ano extraído da coluna 'DATA'
df.Ano = year.(df.DATA)

# Definir os anos, rótulos e cores
dados = [
    (ano = 2023, cor = :lightblue, label = "2023: Temperatura [°C]"),
    (ano = 2022, cor = :green, label = "2022: Temperatura [°C]"),
    (ano = 2021, cor = :lightcoral, label = "2021: Temperatura [°C]"),
    (ano = 2013, cor = :red, label = "2013: Temperatura [°C]"),
    (ano = 2012, cor = :black, label = "2012: Temperatura [°C]"),
    (ano = 2011, cor = :orange, label = "2011: Temperatura [°C]")
]

# Inicializar o gráfico
p = scatter(
    dayofyear.(df[df.Ano .== 2023, :DATA]), df[df.Ano .== 2023, :TEMPERATURA_AR_BULBO_SECO],
    label = "2023: Temperatura [°C]",
    color = :lightblue, alpha = 0.6, xlabel = "Dia do Ano", ylabel = "Temperatura [°C]", 
    legend = :bottomleft, legendfontsize = 8,
    ylims = (0, 50), linewidth = 1.5, yticks = 0:10:50, 
    tickfontsize = 8, guidefontsize = 8
)

# Adicionar os dados dos outros anos usando um loop
for (ano, cor, label) in dados[2:end]
    scatter!(
        dayofyear.(df[df.Ano .== ano, :DATA]), df[df.Ano .== ano, :TEMPERATURA_AR_BULBO_SECO],
        label = label,
        color = cor, alpha = 0.6, linewidth = 1.5
    )
end

# Exibir o gráfico
display(p)
In [694]:
# Selecionar apenas colunas numéricas
numeric_df = df[:, [col for col in names(df) if eltype(df[!, col]) <: Number]]

# Calcular matriz de correlação
cor_matrix = cor(Matrix(numeric_df))
n_vars = size(cor_matrix, 1)
var_names = names(numeric_df)

# Criar máscara triangular inferior
mask = [i >= j for i in 1:n_vars, j in 1:n_vars]

# Aplicar máscara: valores fora do triângulo ficam como NaN
masked_cor = cor_matrix .* mask
masked_cor[.!mask] .= NaN

# Inverter as linhas da matriz para alinhar com os nomes invertidos no eixo Y
reversed_masked_cor = reverse(masked_cor, dims=1)
reversed_names = reverse(var_names)

# Criar heatmap
plt = heatmap(
    var_names, reversed_names,  # Eixos com nomes originais e invertidos
    reversed_masked_cor,        # Matriz invertida verticalmente
    color = :RdBu, clims = (-1, 1),
    xrot = 90, size = (1000, 1000),
    colorbar_title = "",
    title = "Matriz de Correlação",
    xticks = (1:n_vars, var_names),  # Forçar todos os ticks no eixo X
    yticks = (1:n_vars, reversed_names)  # Forçar todos os ticks no eixo Y
)

# Adicionar anotações nas posições corretas (considerando a inversão vertical)
for i in 1:n_vars
    for j in 1:i  # Apenas triângulo inferior
        value = round(cor_matrix[i, j], digits=2)
        text_color = abs(value) > 0.5 ? :white : :black
        # Posição X: coluna j, Posição Y: linha ajustada pela inversão
        annotate!(plt, j - 0.5, n_vars - i + 0.5, text("$value", 8, text_color, :center))
    end
end

display(plt)
In [695]:
using TimeSeries
# Passo 1: Criar uma série temporal com os dados de temperatura usando TimeArray
temperature_ts = TimeArray(df_2021.DATA, df_2021.TEMPERATURA_AR_BULBO_SECO)

# Passo 2: Calcular a tendência usando uma média móvel
# Vamos usar uma janela de 30 dias para a média móvel (ajuste conforme necessário)
window_size = 30
trend_values = [mean(values(temperature_ts)[max(1, i - window_size ÷ 2):min(end, i + window_size ÷ 2)]) for i in 1:length(temperature_ts)]
trend = TimeArray(timestamp(temperature_ts), trend_values)

# Passo 3: Ajustar um modelo de regressão linear à tendência
# Criar um DataFrame com os dados da tendência para usar no GLM
trend_df = DataFrame(DATA = timestamp(trend), Tendencia = values(trend))
trend_df.time_index = 1:nrow(trend_df)  # Adicionar um índice de tempo para a regressão

# Ajustar o modelo de regressão linear
model = lm(@formula(Tendencia ~ time_index), trend_df)

# Passo 4: Prever os valores da linha de regressão
trend_df.regression = predict(model)

# Passo 5: Remover a tendência dos dados originais para obter a componente sazonal e residual
detrended_values = values(temperature_ts) - values(trend)
detrended = TimeArray(timestamp(temperature_ts), detrended_values)

# Passo 6: Calcular a sazonalidade (assumindo um período sazonal fixo, por exemplo, 30 dias)
period = 30
seasonal_values = zeros(length(temperature_ts))
for i in 1:period
    idx = i:period:length(temperature_ts)  # Índices correspondentes ao mesmo ponto no período
    seasonal_values[idx] .= mean(values(detrended)[idx])  # Média dos valores correspondentes
end
seasonal = TimeArray(timestamp(temperature_ts), seasonal_values)

# Passo 7: Calcular os resíduos
residual_values = values(detrended) - values(seasonal)
residual = TimeArray(timestamp(temperature_ts), residual_values)

# Passo 8: Visualizar a decomposição em um layout com 4 subplots
# Criar os subplots
p1 = plot(timestamp(temperature_ts), values(temperature_ts), label = "Dados Originais", lw = 2, title = "Dados Originais", xlabel = "", ylabel = "Temperatura (°C)")
p2 = plot(timestamp(trend), values(trend), label = "Tendência", lw = 2, title = "Tendência", xlabel = "", ylabel = "Temperatura (°C)")
plot!(p2, timestamp(trend), trend_df.regression, label = "Regressão Linear", lw = 2, linestyle = :dash, linecolor = :red)  # Adicionar a linha de regressão
p3 = plot(timestamp(temperature_ts), values(seasonal), label = "Sazonalidade", lw = 2, title = "Sazonalidade", xlabel = "", ylabel = "Temperatura (°C)")
p4 = plot(timestamp(temperature_ts), values(residual), label = "Resíduos", lw = 2, title = "Resíduos", xlabel = "", ylabel = "Temperatura (°C)")

# Adicionar uma linha horizontal no gráfico dos resíduos para representar a média dos resíduos
mean_residual = mean(values(residual))  # Média dos resíduos
hline!(p4, [mean_residual], label = "Média dos Resíduos", linestyle = :dash, linecolor = :red)

# Exibir todos os subplots em um layout
plot(p1, p2, p3, p4, layout = (4, 1), size = (900, 600))
In [696]:
# Gerar histogramas para cada coluna e armazenar os gráficos em um vetor
plots = []
for col in names(numeric_df)
    # Remover valores missing ou NaN da coluna usando skipmissing
    clean_data = collect(skipmissing(numeric_df[!, col]))
    
    # Criar histograma normalizado (com density=true)
    p = histogram(clean_data, 
                  xlabel=col, 
                  legend=:none,
                  size=(300, 200),
                  color=:dodgerblue,         # Cor personalizada
                  linewidth=0,
                  alpha=0.5,
                  nbins=15,
                  normalize=:pdf,
                  xguidefontsize=7)     # Diminuir o tamanho da fonte do xlabel)         # Normalizar o histograma para probabilidade (pdf)
    
    # Adicionar densidade
    density!(p, clean_data, 
             color=:blue,          # Cor da linha de densidade
             linewidth=2,         # Espessura da linha de densidade
             alpha=0.7)           # Transparência da curva de densidade

    # Adicionar o gráfico ao vetor
    push!(plots, p)
end

# Organizar os gráficos em subplots
plot(plots..., layout=(4, 5), size=(1200, 600))
In [697]:
# Agrupar por dia para obter a precipitação total diária
df_daily = combine(groupby(df, :DATA), :PRECIP_mm => sum => :Precipitação_Diária)

# Ordenar o DataFrame por data (caso não esteja ordenado)
sort!(df_daily, :DATA)

# Calcular a média móvel exponencial (EMA) com um fator de suavização
function ema(values, α=0.1)
    ema_values = similar(values)
    ema_values[1] = values[1]
    for i in 2:length(values)
        ema_values[i] = α * values[i] + (1 - α) * ema_values[i-1]
    end
    return ema_values
end

# Calcular a EMA para a precipitação diária
α = 0.1  # Fator de suavização (ajuste conforme necessário)
df_daily[!, :EMA_Precipitação] = ema(df_daily[!, :Precipitação_Diária], α)

# Plotar a série temporal com a linha de média ponderada (EMA)
plot(df_daily[!, :DATA], df_daily[!, :Precipitação_Diária], 
    title="Série Temporal de Precipitações Diárias", 
    xlabel="Data", ylabel="Precipitação (mm)", 
    label="Precipitação Diária", lw=2, color=:dodgerblue, seriestype=:line, alpha=0.6)

plot!(df_daily[!, :DATA], df_daily[!, :EMA_Precipitação], 
    label="Média Móvel Exponencial (EMA)", lw=2, color=:red, linestyle=:dash, alpha=0.6)

# Melhorar a legenda e o layout
plot!(legend=:topright, grid=true)
In [730]:
# Extrair o mês da coluna DATA
df[!, :MES] = month.(df[!, :DATA])

# Agrupar por mês e somar a precipitação
df_monthly_precip = combine(groupby(df, :MES), :PRECIP_mm => sum => :Precipitação_Total)

# Ordenar os meses pela precipitação total (do maior para o menor)
sort!(df_monthly_precip, :Precipitação_Total, rev=true)

# Criar o gráfico de barras
bar(df_monthly_precip.MES, 
    df_monthly_precip.Precipitação_Total, 
    xlabel="Mês", 
    ylabel="Precipitação Total (mm)", 
    title="Precipitação Total por Mês", 
    legend=false, 
    color=:lightblue, 
    alpha=0.7,
    lw=0,
    xticks=(1:12, ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]),  # Nomes dos meses
    xrotation=45)  # Rotacionar os rótulos do eixo x para melhor legibilidade

# Adicionar os valores em cima de cada barra (com 2 dígitos)
for (i, precip) in enumerate(df_monthly_precip.Precipitação_Total)
    precip_formatado = round(precip, digits=2)  # Arredonda para 2 dígitos
    annotate!(df_monthly_precip.MES[i], precip + 0.05 * maximum(df_monthly_precip.Precipitação_Total), 
              text("$precip_formatado", :center, 8))  # Adiciona o valor formatado acima da barra
end

# Exibir o gráfico
plot!()
In [729]:
# Filtrar apenas os dias com precipitação maior que 0
df_chuva = filter(row -> row.PRECIP_mm > 0, df)

# Agrupar por mês e contar o número de dias com chuva
df_chuva_mensal = combine(groupby(df_chuva, :MES), nrow => :Dias_Com_Chuva)

# Ordenar os meses pelo número de dias com chuva (do maior para o menor)
sort!(df_chuva_mensal, :Dias_Com_Chuva, rev=true)

# Criar o gráfico de barras
bar(df_chuva_mensal.MES, 
    df_chuva_mensal.Dias_Com_Chuva, 
    xlabel="Mês", 
    ylabel="Dias com Chuva", 
    title="Dias com Chuva por Mês", 
    legend=false, 
    color=:blue, 
    alpha=0.6,
    lw=0,
    xticks=(1:12, ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]),  # Nomes dos meses
    ylim=(0, maximum(contagem_por_ano.QUANTIDADE) * 0.06),  # Ajustar o limite superior do eixo y
    xrotation=45)  # Rotacionar os rótulos do eixo x para melhor legibilidade

# Adicionar os valores em cima de cada barra
for (i, dias) in enumerate(df_chuva_mensal.Dias_Com_Chuva)
    annotate!(df_chuva_mensal.MES[i], dias + 0.05 * maximum(df_chuva_mensal.Dias_Com_Chuva), 
              text("$dias", :center, 8))  # Adicionar o valor acima da barra
end

# Exibir o gráfico
plot!()
In [700]:
# Passo 1: Extrair o dia e o mês da coluna DATA
df[!, :DIA] = day.(df[!, :DATA])
df[!, :MES] = month.(df[!, :DATA])

# Passo 2: Filtrar apenas os dias 23/02
df_23_02 = filter(row -> row.DIA == 23 && row.MES == 2, df)

# Passo 3: Filtrar apenas os dias com precipitação maior que 0
df_23_02_chuva = filter(row -> row.PRECIP_mm > 0, df_23_02)
7×24 DataFrame
RowDATAHORAPRECIP_mmPRESSAO_ATMOSFERICA_NIVEL_ESTACAO_mbPRESSAO_ATMOSFERICA_MAX_mbPRESSAO_ATMOSFERICA_MIN_mbRADIACAO_GLOBAL_kjm2TEMPERATURA_AR_BULBO_SECOTEMPERATURA_PONTO_DE_ORVALHOTEMPERATURA_MAXIMATEMPERATURA_MINIMATEMPERATURA_ORVALHO_MAXTEMPERATURA_ORVALHO_MINUMIDADE_RELATIVA_MAXIMA_percentUMIDADE_RELATIVA_MINIMA_percentUMIDADE_RELATIVA_AR_percentVENTO_DIRECAOVENTO_RAJADA_MAXIMA_msVENTO_VELOCIDADE_msANOMonthYearAnoMESDIA
DateAnyFloat64Float64Float64Float64RealFloat64Float64Float64Float64Float64Float64Int64Int64Int64Int64Float64Float64Int64StringInt64Int64Int64
12007-02-2321:00:0025.6971.5972.1970.8789.022.320.925.521.121.319.49373921715.13.320072007022007223
22009-02-2321:00:000.4968.8968.8967.1149.224.619.828.724.620.718.5775675399.74.620092009022009223
32009-02-2323:00:004.2971.6971.6969.50.821.219.123.721.120.018.98877883413.86.320092009022009223
42015-02-2319:00:000.2967.6968.5967.61463.129.319.629.826.621.219.17255561529.43.220152015022015223
52015-02-2321:00:003.4969.9970.0968.0143.821.819.329.721.720.018.686528616014.34.320152015022015223
62018-02-2314:00:001.0972.0972.2971.8344.525.020.426.925.020.719.87667762996.21.620182018022018223
72018-02-2315:00:002.0971.3972.2971.2505.725.222.325.223.722.320.58576842994.71.020182018022018223
In [701]:
# Agrupar por mês e encontrar o dia com a maior precipitação
df_max_chuva_mensal = combine(groupby(df, :MES), :PRECIP_mm => maximum => :Max_Precipitação)

# Juntar os dados originais para obter as datas correspondentes aos máximos
df_resultado = innerjoin(df, df_max_chuva_mensal, on=[:MES, :PRECIP_mm => :Max_Precipitação])

# Selecionar apenas as colunas relevantes (DATA, MES, PRECIP_mm)
df_resultado = df_resultado[:, [:DATA, :MES, :PRECIP_mm]]

# Ordenar os resultados por mês
sort!(df_resultado, :MES)
12×3 DataFrame
RowDATAMESPRECIP_mm
DateInt64Float64
12008-01-31147.4
22007-02-13247.0
32008-03-15333.8
42003-04-08427.2
52009-05-16519.6
62005-06-1266.2
72013-07-1976.2
82019-08-0782.2
92006-09-0892.6
102010-10-281047.0
112021-11-051139.6
122010-12-121225.4
In [702]:
using Plots

# Definir os anos, rótulos e cores
dados = [
    (ano = 2023, cor = :lightblue, label = "2023: Precipitação [mm]"),
    (ano = 2013, cor = :green, label = "2013: Precipitação [mm]"),
    (ano = 2003, cor = :lightcoral, label = "2003: Precipitação [mm]"),
    (ano = 2004, cor = :pink, label = "2004: Precipitação [mm]"),
    (ano = 2005, cor = :black, label = "2005: Precipitação [mm]"),
    (ano = 2006, cor = :orange, label = "2006: Precipitação [mm]")
]

# Inicializar o gráfico
p = plot(
    dayofyear.(df[df.Ano .== 2023, :DATA]), df[df.Ano .== 2023, :PRECIP_mm],
    label = "2023: Precipitação [mm]",
    color = :lightblue, alpha = 0.6, xlabel = "Dia do Ano", ylabel = "Precipitação [mm]", 
    legend = :topleft, legendfontsize = 8,
    ylims = (0, 50), linewidth = 1.5, yticks = 0:10:50, 
    tickfontsize = 8, guidefontsize = 8
)

# Adicionar os dados dos outros anos usando um loop
for (ano, cor, label) in dados[2:end]
    plot!(
        dayofyear.(df[df.Ano .== ano, :DATA]), df[df.Ano .== ano, :PRECIP_mm],
        label = label,
        color = cor, alpha = 0.6, linewidth = 1.5
    )
end

# Adicionar uma linha horizontal em 30 mm para destacar os dias com chuva intensa
hline!([20], color = :red, linestyle = :dash, label = "Limite de 20 mm", linewidth = 2)

# Destacar os pontos onde a precipitação foi maior que 30 mm
for (ano, cor, label) in dados
    dias_chuva_intensa = dayofyear.(df[(df.Ano .== ano) .& (df.PRECIP_mm .> 20), :DATA])
    precip_chuva_intensa = df[(df.Ano .== ano) .& (df.PRECIP_mm .> 20), :PRECIP_mm]
    scatter!(
        dias_chuva_intensa, precip_chuva_intensa,
        color = cor, markersize = 6, label = nothing, markerstrokecolor = :black
    )
end

# Exibir o gráfico
display(p)